#ifndef _YM2612_VALUE_
#define _YM2612_VALUE_
//=======================================================================================================
// YM2612Value
// Author: Landon Podbielski
// Description: YM2612Value wraps up everything you need to deal with a single register value. It offers a
//				simplified interface for initializing a register, and ensuring the value inside the register
//				stays within set bounds. It also encapsulates some VST specific channel details, such as
//				the MIDI channel/CC number that the parameter is hooked up to, providing an interface for
//				VST automation features.
//-------------------------------------------------------------------------------------------------------

#include "YM2612Enum.h"

//-------------------------------------------------------------------------------------------------------
//YM2612Value - Pairs a parameter with a value and 
//              ensures it stays within range
//-------------------------------------------------------------------------------------------------------
struct YM2612StateData;
class YM2612Value
{
public:
	YM2612Value();
	YM2612Value( YM2612Param param, unsigned char min, unsigned char max, unsigned char value = 0 );
	void InitializeDefaults();
	void Init( YM2612Param param, unsigned char min, unsigned char max, unsigned char value = 0 );
	void MidiModified();

	//Functions for dealing with Value
	void SetValue( int value );
	unsigned char GetValue() const { return _value; }
	float GetValueAsFloat() const { return (float)(_value * (1.0f / (float)_max)) + 0.001f; }
	void SetValueFromFloat( float val ) { _value = (unsigned char)(val * _max); }

	//Getters and Setters
	unsigned char GetMin() const { return _min; }
	unsigned char GetMax() const { return _max; }
	YM2612Param GetParam() const { return _param; }

	void SetIndex(int index) { _index = index; }
	int GetIndex() const { return _index; }

	void SetOp(int op) { _op = op; }
	int GetOp() const { return _op; }

	void SetChannel( int channel ) { _channel = channel; }
	int GetChannel() const { return _channel; }

	void SetMidiLearn( bool learn ) { _midiLearn = learn; if( learn == true ) {MidiModified();} }
	bool GetMidiLearn() const { return _midiLearn; }

	void SetMidiHookup( int midi ) { _midi = midi; if( midi != 0 ) {MidiModified();} }
	int GetMidiHookup() const { return _midi; }

	void SetOwner( YM2612StateData* owner ) { _owner = owner; }
	YM2612StateData* GetOwner() { return _owner; }

private:
	YM2612Param _param;
	unsigned char _min;
	unsigned char _max;
	unsigned char _value;
	int _index;
	int _channel;
	int _op;
	int _midi;
	bool _midiLearn;
	YM2612StateData* _owner;
};

//-------------------------------------------------------------------------------------------------------
//YM2612Values - A collection of YM2612Value structures
//-------------------------------------------------------------------------------------------------------
struct YM2612Values
{
	YM2612Values();
	YM2612Value& GetParam( YM2612Param param );
	YM2612Value* GetParamByIndex( int index );	
	YM2612Value* operator[]( int index );

	//Casts an index to a pointer in the class data to a YM2612Value
	YM2612Value* CastValueData( int index );

	void SetChannel( int channel );
	void SetOp( int op );

	//This structure is completely useless unless it is inherited from with a 
	//class which defines a number YM2612Value structures as it's data members.
	//You must implement NumParams and ensure it returns the number of YM2612Value
	//structures you are wrapping.
	virtual int NumParams() = 0;
	int Channel;
	int Op;
};

#endif //_YM2612_VALUE_